package ru.spbu.math.android.cbrf.view;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;
import ru.spbu.math.android.cbrf.R;
import ru.spbu.math.android.cbrf.charts.ChartsActivity;
import ru.spbu.math.android.cbrf.dataprovider.DataProvider;
import ru.spbu.math.android.cbrf.dataprovider.IllegalStockItemsCombinationException;
import ru.spbu.math.android.cbrf.model.Rate;
import ru.spbu.math.android.cbrf.model.RateType;
import ru.spbu.math.android.cbrf.model.StockItem;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class UsdCourseWidget extends AppWidgetProvider {


    private static final String LOG_TAG = "RateTypeWidget";

    public static final String UPDATE_CONTENT_ACTION = "WRITE";
    public static final String GET_UPDATES_ACTION = "GETUPDATES";

    private static boolean isServiceStarted = false;
    private static List<WidgetContainer> widgets = new ArrayList<WidgetContainer>();

    /*
     *      registering our widget with em ID and appropriate RateType.
     */
    public static void registerWidget(Context context, int wID, RateType type) {

        Log.d(LOG_TAG, "Registering widget with ID: " + wID + "; for RateType: " + type.getSourceCode() + "/" + type.getTargetCode());

        //  creating views, intent and container
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        Intent callDrawingGraphicActivity = new Intent(context, ChartsActivity.class);
        Bundle extras = new Bundle();
        extras.putString("SOURCE", type.getSourceCode());
        extras.putString("TARGET", type.getTargetCode());
        callDrawingGraphicActivity.putExtras(extras);

        callDrawingGraphicActivity.setFlags(wID);
        PendingIntent callIntent = PendingIntent.getActivity(context, 0, callDrawingGraphicActivity, wID);
        views.setOnClickPendingIntent(R.id.Widget, callIntent);

        WidgetContainer container = findWidgetByID(wID);
        container.views = views;
        container.type = type;

        //  showing
        updateWidget(context, container);

        //  calling DataProvider for a first values on a widget
        try {

            DataProvider dataProvider = DataProvider.getInstance(context);
            updateWidgetWithProvider(context, dataProvider, container);
            updateWidget(context, container);               //  showing

        } catch (IllegalStockItemsCombinationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /*
     *  if it a first start of our widget
     *  we most reload all saved preferences and start the Service.
     */
    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        //  setting initial views   or  updating widgets per 10-seconds
        DataProvider dataProvider = DataProvider.getInstance(context);
        for (int wID : appWidgetIds) {

            WidgetContainer container = findWidgetByID(wID);

            if (container == null) {
                //  in case that we have not this widget in list
                container = new WidgetContainer(wID);
                RemoteViews initialViews = getViewsByFourParameters(context, wID, R.layout.initial_widget,
                        R.id.InitialView, ItemsConfigurationActivity.class);
                container.views = initialViews;
                widgets.add(container);

                appWidgetManager.updateAppWidget(wID, initialViews);            //  showing
            } else {
                //  in case that we already have that widget
                try {

                    updateWidgetWithProvider(context, dataProvider, container);
                    appWidgetManager.updateAppWidget(wID, container.views);     //  showing

                } catch (IllegalStockItemsCombinationException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        String action = intent.getAction();
        if (action.equals(UPDATE_CONTENT_ACTION)) {
            //  in this case we should obtain updates
            //  by the sending Broadcast way.

            Bundle extras = intent.getExtras();
            RateType updatedRateType = new RateType(extras.getString("SOURCE"), extras.getString("TARGET"));
            WidgetContainer container = findWidgetByRateType(updatedRateType);
            container.setValuesFromExtras(extras);

            //  showing
            updateWidget(context, container);
        }
        super.onReceive(context, intent);
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);

        //  removing from List
        int wID = appWidgetIds[0];
        widgets.remove(findWidgetByID(wID));
    }

    /*
     *      Class-helper to collect the widget's
     *  ID, RemoteViews
     *  & his associated RateType
     *  in one place.
     */
    /**
	 * @author  Helga
	 */
    class WidgetContainer {
        int id;
        RemoteViews views;
        /**
		 * @uml.property  name="type"
		 * @uml.associationEnd  
		 */
        RateType type;

        WidgetContainer(int id) {
            this.id = id;
        }

        /*
         *      Setting values from the Bundle object.
         */
        public void setValuesFromExtras(Bundle extras) {
            views.setTextViewText(R.id.Name, type.getSourceCode() + "/" + type.getTargetCode());
            views.setTextViewText(R.id.Value, extras.getString("VALUE"));
            views.setTextViewText(R.id.Change, extras.getString("CHANGE"));
            views.setTextViewText(R.id.Date, extras.getString("DATE"));
        }

        /*
         *      Setting values of views from the Rate object.
         */
        public void setValuesFromRate(Context context, Rate rate, double increase) {
            //  creating views, intent and container

            Log.d(LOG_TAG, "increase "+increase);
            if (increase<0.000001 && increase>-0.000001){
                Log.d(LOG_TAG, increase+"");
                views = new RemoteViews(context.getPackageName(), R.layout.widget);
                views.setTextViewText(R.id.Change, "0.00000");
            } else if (increase>0){
                views = new RemoteViews(context.getPackageName(), R.layout.widget_up);
                views.setTextViewText(R.id.Change, "+"+increase);
            } else if (increase<0){
                views = new RemoteViews(context.getPackageName(), R.layout.widget_down);
                views.setTextViewText(R.id.Change, ""+increase);
            }

            Intent callDrawingGraphicActivity = new Intent(context, ChartsActivity.class);
            Bundle extras = new Bundle();
            extras.putString("SOURCE", type.getSourceCode());
            extras.putString("TARGET", type.getTargetCode());
            callDrawingGraphicActivity.putExtras(extras);

            callDrawingGraphicActivity.setFlags(id);
            PendingIntent callIntent = PendingIntent.getActivity(context, 0, callDrawingGraphicActivity, id);
            views.setOnClickPendingIntent(R.id.Widget, callIntent);

            views.setTextViewText(R.id.Name, type.getSourceCode() + "/" + type.getTargetCode());
            views.setTextViewText(R.id.Value, Double.toString(rate.getValue()));

            DateFormat df = new SimpleDateFormat();
            views.setTextViewText(R.id.Date, df.format(rate.getDate()).split(" ")[0]);
        }

    }

    /*
     *      Updating widget views with the DataProvider.
     */
    private static void updateWidgetWithProvider(Context context, DataProvider dataProvider, WidgetContainer container)
            throws IllegalStockItemsCombinationException {
        if (container.type != null) {
            StockItem src = new StockItem(), trg = new StockItem();
            src.setCode(container.type.getSourceCode());
            trg.setCode(container.type.getTargetCode());
            Rate rate = dataProvider.getLatestRate(src, trg);
            if (rate!=null){
                double increase = dataProvider.getIncrease(src, trg);
                container.setValuesFromRate(context, rate, increase);
            } else {

                container.views.setTextViewText(R.id.Name, "No");
                container.views.setTextViewText(R.id.Value, "Network");

                Log.d(LOG_TAG, "Returned rate is Null.");
            }
        }
    }

    /*
     *      Finding WidgetContainer from a 'widgets' list by his ID
     */
    private static WidgetContainer findWidgetByID(int wID) {
        for (WidgetContainer c : widgets) {
            if (c.id == wID) {
                return c;
            }
        }
        return null;
    }

    /*
     *      Finding WidgetContainer from a 'widgets' list by his RateType
     */
    private static WidgetContainer findWidgetByRateType(RateType t) {
        for (WidgetContainer w : widgets) {
            if (t.equals(w.type)) {
                return w;
            }
        }
        return null;

    }


    /*
      *     specific method wanted only in one time of this class declaration
       */
    private static RemoteViews getViewsByFourParameters(Context c, int wID, int layoutResID, int onClickResId, Class activityClass) {
        RemoteViews views = new RemoteViews(c.getPackageName(), layoutResID);
        Intent callChooseContentActivity = new Intent(c, activityClass);
        callChooseContentActivity.setFlags(wID);

        PendingIntent callIntent = PendingIntent.getActivity(c, 0, callChooseContentActivity, wID);
        views.setOnClickPendingIntent(onClickResId, callIntent);
        return views;
    }

    /*
      *     update widget through WidgetManager with WidgetContainer
       */
    private static void updateWidget(Context context, WidgetContainer container) {

        // Push update for this widget to the home screen
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        manager.updateAppWidget(container.id, container.views);
    }
}
